<?php
/**
 * Created by PhpStorm.
 * User: jjj
 * Date: 2017/8/23
 * Time: 16:36
 */

namespace app\common\model;


use app\common\utils\DateTimeUtil;
use library\JPushZDY;
use think\Db;
use think\db\Query;
use think\Model;

/**
 * Class UserNoticeMessage
 * @package app\common\model
 *
 * @property integer id
 * @property integer userid
 * @property string title
 * @property string content
 * @property string created
 * @property integer type
 * @property integer message_type
 * @property null|object extras
 */
class UserNoticeMessage extends Model
{
    protected $table = 'user_notice_message';
    protected $pk = 'id';
    protected $field = [
        'id',
        'userid',
        'content',
        'type',
        'message_type',
        'extras',
        'title',
    ];

    const TYPE_PRIVATE  = 1;
    const TYPE_PUBLIC   = 2;

    const MESSAGE_TYPE_SYSTEM   = 1;
    const MESSAGE_TYPE_ACTIVITY = 2;
    private static $MessageTypeKeys = [
        self::MESSAGE_TYPE_SYSTEM   => 'system',
        self::MESSAGE_TYPE_ACTIVITY => 'activity',
    ];


    public static function get($data, $with = [], $cache = false)
    {
        $model = parent::get($data, $with, $cache);
        if ($model) $model->decodeJson();
        return $model;
    }

    public function save($data = [], $where = [], $sequence = null)
    {
        $this->encodeJson();
        $result = parent::save($data, $where, $sequence);
        $this->decodeJson();
        return $result;
    }

    public function encodeJson() {
        if (isset($this->extras)) {
            if (is_array($this->extras) || is_object($this->extras)) {
                $this->extras = json_encode($this->extras,JSON_UNESCAPED_UNICODE);
            }
        }
    }
    public function decodeJson() {
        if (isset($this->extras)) {
            if (is_string($this->extras)) {
                $this->extras = json_decode($this->extras);
            }
        }
    }

    public static function myTotal(int $uid) {
        $sql = <<<SQL
SELECT m.message_type AS "type", count(m.id) num
FROM user_notice_message m LEFT JOIN user_notice_message_read r ON m.id = r.message_id
WHERE (m.type = 2 OR (m.type = 1 AND m.userid = :uid)) AND r.message_id ISNULL 
GROUP BY m.message_type
SQL;
        $re = Db::query($sql, ['uid'=>$uid]);
        $result = new \stdClass();
        foreach (self::$MessageTypeKeys as $type => $key) {
            $latest = self::getLatest($uid, $type);
            foreach ($re as $item) {
                if ($type == $item['type']) {
                    $result->$key = [
                        'type' => $type,
                        'num' => $item['num'],
                        'latest' => $latest
                    ];
                }
            }
            if (!isset($result->$key)) {
                $result->$key = [
                    'type' => $type,
                    'num' => 0,
                    'latest' => $latest
                ];
            }
        }
        return $result;
    }

    public static function getLatest($uid, $messageType) {
        $filter = '';
        $params = ['mt' => $messageType];
        if (self::TYPE_PRIVATE == $messageType) {
            $filter .= ' AND m.userid = :uid ';
            $params['uid'] = $uid;
        }
        $aql = <<<SQL
SELECT m.id,m.title,m.created, r.message_id IS NOT NULL AS has_read
FROM user_notice_message m LEFT JOIN user_notice_message_read r ON m.id = r.message_id
WHERE m.type = :mt {$filter}
ORDER BY m.id DESC 
LIMIT 1
SQL;
        $re = Db::query($aql, $params);
        if (empty($re)) return null;
        $re = $re[0];
        $re['created'] = DateTimeUtil::format($re['created']);
        return $re;
    }

    /**
     * 通知列表
     *
     * @param int $uid
     * @param null $type
     * @param int $limit
     * @param int $offset
     * @return mixed
     */
    public static function myList(int $uid, $type = null, int $limit = 10, int $offset = 0) {
        $filter = '';
        $params = ['uid' => $uid, 'limit' => $limit, 'offset' => $offset];
        if (null != $type) {
            $filter .= ' AND m.message_type=:mt ';
            $params['mt'] = $type;
        }
        $sql = <<<SQL
SELECT m.*,r.message_id IS NOT NULL AS has_read
FROM user_notice_message m LEFT JOIN user_notice_message_read r ON r.message_id = m.id
WHERE (m.type = 2 OR (m.type = 1 AND m.userid = :uid)) {$filter}
ORDER BY m.id DESC 
LIMIT :limit OFFSET :offset
SQL;

        $list = Db::query($sql, $params);

        $time = null;
        $count = 0;
        foreach ($list as & $item) {
            $item['read'] = $item['has_read'] ? 1 : 0;
            $item['created'] = substr($item['created'],0,19);
            $item['createdTime'] = DateTimeUtil::format($item['created']);
            $item['extras'] = json_decode($item['extras']);

            if ($time == $item['createdTime']) {
                $item['displayTime'] = false;
                $count++;
            } else {
                $item['displayTime'] = true;
                $time = $item['createdTime'];
                $count = 0;
            }
        }

        return $list;
    }

    /**
     * 构建extras
     *
     * @param $type
     * @param $id
     * @return \stdClass
     */
    public static function makeExtras($type, $id) {
        $extra = new \stdClass();
        $extra->linkType = intval($type);
        $extra->linkId = strval($id);
        return $extra;
    }

    /**
     * 添加个人消息
     *
     * @param int $uid
     * @param $title
     * @param string $content
     * @param int $msgType
     * @param null|object $extras
     * @return static
     */
    public static function addMsg($uid, $title, $content, $msgType = self::MESSAGE_TYPE_SYSTEM, $extras = null) {
        $model = new static();
        $model->userid = (int) $uid;
        $model->title = $title;
        $model->content = $content;
        $model->message_type = $msgType;
        $model->extras = $extras ?? new \stdClass();
        $model->type = self::TYPE_PRIVATE;
        $model->save();
        return $model;
    }

    /**
     * 添加公共消息
     *
     * @param $title
     * @param string $content
     * @param int $msgType
     * @param null $extras
     * @return static
     */
    public static function addPublicMsg($title, $content, $msgType = self::MESSAGE_TYPE_SYSTEM, $extras = null) {
        $model = new static();
        $model->userid = 0;
        $model->title = $title;
        $model->content = $content;
        $model->message_type = $msgType;
        $model->extras = $extras ?? new \stdClass();
        $model->type = self::TYPE_PUBLIC;
        $model->save();
        return $model;
    }


    /**
     * 发送邀请注册通知
     *
     * @param $uid
     * @param $mobile
     * @param $credit
     */
    public static function sendInviteRegisterMessage($uid, $mobile, $credit,$text='掌乾财经：您邀请的“%s”已完成注册，恭喜您获得%s积分。',$title='邀请注册') {
        $content = sprintf($text, $mobile, $credit);
        self::addMsg($uid,$title, $content, self::MESSAGE_TYPE_SYSTEM);
//        JPushZDY::pushUsers($uid, $content);
    }
    /**
     * 发送邀请购买通知
     *
     * @param $uid
     * @param $mobile
     * @param $title
     * @param $credit
     */
    public static function sendInviteBuyMessage($uid, $mobile, $title, $credit) {
        $content = sprintf('掌乾财经：您邀请的“%s”已购买%s，恭喜您获得%s积分。',$mobile, $title, $credit);
        self::addMsg($uid,'推广消费', $content, self::MESSAGE_TYPE_SYSTEM);
//        JPushZDY::pushUsers($uid, $content);
    }

    /**
     * 设置消息的已读状态
     *
     * @param int $uid
     */
    public static function setRead(int $uid) {
        $sql = <<<SQL
INSERT INTO user_notice_message_read (userid, message_id)
  SELECT
    $uid,
    m.id
  FROM user_notice_message m LEFT JOIN user_notice_message_read r ON r.message_id = m.id
  WHERE m.type = 2 AND r.message_id IS NULL
  UNION
  SELECT
    $uid,
    m.id
  FROM user_notice_message m LEFT JOIN user_notice_message_read r ON r.message_id = m.id
  WHERE m.type = 1 AND m.userid = $uid AND r.message_id IS NULL
SQL;
        Db::execute($sql);
    }

    /**
     * @param $uid
     * @param $msgId
     */
    public static function read($uid, $msgId) {
        $sql = <<<SQL
INSERT INTO user_notice_message_read (userid, message_id) VALUES (:uid, :msg_id) ON CONFLICT DO NOTHING 
SQL;
        Db::execute($sql, ['uid'=>$uid, 'msg_id'=>$msgId]);
    }

}